﻿#include "symath.h"
#include <iostream>
#include "sygraph.h"
#include <conio.h>
#include "sytime.h"
#include <Windows.h>
#include "sydata.h"
#include "log.h"

using namespace std;
using namespace sy::math;
using namespace sy::draw;
using namespace sy::time;
using namespace sy::tools;

struct Camera
{
	Mat4 translate;
	Mat4 rotate;

public:
	// 创建一个不动的摄像机 ，(x, y, z) 为摄像机的位置，摄像机看向原点
	static Camera CreateCamera(float x, float y, float z)
	{
		Camera ret;

		Vector4 cameraPosition = Vector4(-x, -y, -z, 1);
		Mat4 rotate, translate;
		Vector4 cameraDir = Vector4(x, y, z, 0).Normalize();
		// 世界坐标的上
		Vector4 worldUp = Vector4::Up();
		Vector4 right = Vector4::Cross(cameraDir, worldUp);
		Vector4 cameraUp = Vector4::Cross(right, cameraDir);
		rotate.SetRow(0, right);
		rotate.SetRow(1, cameraUp);
		rotate.SetRow(2, cameraDir.Normalize());
		rotate[3][3] = 1.0f;

		translate.SetCol(3, cameraPosition);

		ret.rotate = rotate;
		ret.translate = translate;
		return ret;
	}
};

Canvas* canvas = nullptr;


int main(int argc, char *argv[])
{
	Log().Write("sunyu");


	// 初始化
	canvas = Canvas::GetInstance();

	// 产生正方体表面数据
	sy::data::GenData(40000);

	// 加载顶点数据
	vector<float>& data = sy::data::Vertex();
	sy::data::LoadData(data, FilePath());


	Mat4 transform = Mat4::Identity();				// 变换矩阵
	Mat4 perspective = Mat4::Perspective(60,1.0f);	// 透视矩阵
	Camera camera = Camera::CreateCamera(0,2,5);	// 摄像机
	Mat4 rotatePerFrame;							// 每帧得旋转计算
	float angleSpeed = 30;							// 旋转速度 (度 / 秒)
	float curAngle = 0;
	float fpsTime = 0;								// FPS 每秒更新一次

	canvas->InitCanvas(screenX, screenY);

	while (!_kbhit())
	{

		// 清屏
		cleardevice();
		
		// 更新变换矩阵
		transform = Mat4::Identity();

		// 计算时间
		Time().Update();

		// 更新角度值
		curAngle += angleSpeed * Time().deltaTime;
		if (curAngle > 360)
			curAngle -= 360;

		// 添加模型矩阵
		rotatePerFrame = Mat4::Rotate(0, curAngle, 0);
		transform.AddRotate(rotatePerFrame);

		// 添加摄像机
		transform.AddTranslate(camera.translate);
		transform.AddRotate(camera.rotate);

		// 添加投影矩阵
		transform.AddPerspective(perspective);

		// 计算顶点屏幕坐标并显示
		for (int i = 0; i < data.size() / 4; i++)
		{
			// 取得数据
			Vector4 point = Vector4(data[i*4],data[i*4+1],data[i*4+2],data[i*4+3]);
			
			// 坐标变换到 裁剪坐标
			point = transform * point;	

			// 坐标裁剪（去掉看不到得点）
			if (abs(point.x) > point.w || abs(point.y) > point.w || abs(point.z) > point.w)
			{
				continue;
			}

			// 裁剪坐标 变换到 NDC 坐标
			point = point.Normalize();
			

			// 绘制
			canvas->Putpixel(point.x * sy::draw::View2Screen,point.y * sy::draw::View2Screen, point.z * sy::draw::View2Screen);
		}
		TCHAR FPS[16];
		if (Time().time >= fpsTime)
		{
			wsprintf(FPS, TEXT("FPS : %d"), (int)(1.0 / Time().deltaTime));
			fpsTime += 1;
		}
		setcolor(RGB(255, 255, 0));
		outtextxy(0, 0, FPS);
		canvas->Show();
	}

	canvas->Close();
	system("pause");
	return 0;
}